package mafiagame.tester;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import aimclient.JoscarTester;
import mafiagame.Action;
import mafiagame.Game;
import mafiagame.MafiaAction;
import mafiagame.MafiaClass;
import mafiagame.MafiaInterface;
import mafiagame.Player;
import mafiagame.SleepAction;
import mafiagame.VoteAction;
import mafiagame.Game.Stage;

public class MafiaTester implements MafiaInterface
{
	static Game g;
	static List<String> inputLog;

	public MafiaTester()
	{
		g = null;
	}

	public static void main(String[] args)
	{
		inputLog = new ArrayList<String>();
		MafiaInterface wrapper = new MafiaTester();
		g = new Game(wrapper);
		g.startGame();
		InputStreamReader isr = new InputStreamReader(System.in);
		BufferedReader br = new BufferedReader(isr);
		System.out
				.println("Enter Commands in the form 'Username;private;message' "
						+ "for private messages or 'Username;message' for public messages");
		while (!g.checkWin())
		{
			try
			{
				String s = br.readLine();
				String[] temp = s.split(";");
				if (temp.length == 2)
				{
					inputLog.add(s);
					g.communicator.processPublicMessage(temp[0], temp[1]);
				} else if (temp.length == 3)
				{
					inputLog.add(s);
					g.communicator.processPrivateMessage(temp[0], temp[2]);
				} else
					System.out.println("Invalid input format.");

			} catch (IOException e)
			{
				e.printStackTrace();
			}
		}

	}

	public void sendPublicMessage(String message)
	{
		System.out.println(">" + message);
	}

	public void sendPrivateMessage(String user, String message)
	{
		System.out.println(">" + user + ": " + message);
	}

	public synchronized void processHeartbeat()
	{
		g.heartbeat();
	}

	public void processPublicMessage(String user, String message)
	{
		if (message.startsWith("save"))
		{
			String[] tokens = message.split(" ");
			try
			{
				File file = new File(tokens[1]);
				FileWriter fstream = new FileWriter(file);
				BufferedWriter out = new BufferedWriter(fstream);
				out.write("Seed: " + Long.toString(g.seed) + "\n");
				for (String s : inputLog)
				{
					String[] temp = s.split(";");
					if (!(temp[1].startsWith("save")))
					{
						out.write(s + "\n");
					}
				}
				System.out.println("successfully saved log to"
						+ file.toString());
				out.close();
			} catch (Exception e)
			{
				e.printStackTrace();
			}
		}
		if (message.startsWith("load"))
		{
			String[] tokens = message.split(" ");
			try
			{
				FileInputStream fstream = new FileInputStream(tokens[1]);
				DataInputStream in = new DataInputStream(fstream);
				BufferedReader br = new BufferedReader(
						new InputStreamReader(in));
				String strLine;
				while ((strLine = br.readLine()) != null)
				{
					System.out.println(strLine);
					if (strLine.startsWith("Seed"))
					{
						String[] seedTokens = strLine.split(" ");
						long seed = new Long(seedTokens[1]);
						g.r = new Random(seed);
					} else
					{
						String[] command = strLine.split(";");
						if (command[1].equals("private"))
							processPrivateMessage(command[0], command[2]);
						else
							processPublicMessage(command[0], command[1]);

					}

					try
					{
						Thread.sleep(5000);
					} catch (InterruptedException e)
					{
					}
				}
				in.close();
			} catch (Exception e)
			{
				e.printStackTrace();

			}
		}
		message = message.toLowerCase();
		if (message.startsWith("heartbeat"))
		{
			String[] tokens = message.split(" ");
			for (int i = 0; i < Integer.parseInt(tokens[1]); i++)
			{
				processHeartbeat();
			}
		}
		if (message.equalsIgnoreCase("actions"))
		{
			for (Player p : g.getLivePlayers())
			{
				List<Action> required = g.requiredActionsForUser
						.get(p.username);
				if (required != null)
				{
					System.out.print(p.username + ":");
					for (Action a : g.requiredActionsForUser.get(p.username))
					{
						System.out.print(" " + a.getCommand());
					}
					System.out.println("");
				}
			}
		}
		if (message.equalsIgnoreCase("livingsleep"))
		{
			for (Player p : g.getLivePlayers())
			{
				processPublicMessage(p.username, "!sleep");
			}
		}
		if (message.equalsIgnoreCase("getphase"))
		{
			System.out.println(g.currentStage);
		}
		if (message.equalsIgnoreCase("add8"))
		{
			g.playerIn("tester1");
			g.playerIn("tester2");
			g.playerIn("tester3");
			g.playerIn("tester4");
			g.playerIn("tester5");
			g.playerIn("tester6");
			g.playerIn("tester7");
			g.playerIn("tester8");
		}
		if (message.equalsIgnoreCase("in"))
		{
			g.playerIn(user);
		}
		if (message.equalsIgnoreCase("start"))
		{
			g.playersGathered();
		}
		if (message.equalsIgnoreCase("votes"))
		{
			g.printVotes();
		}

		g.executePossibleActionsForUser(user, message, true);
	}

	public void processPrivateMessage(String user, String message)
	{
		String msg = message.toLowerCase();

		if (msg.equalsIgnoreCase("listroles"))
		{
			System.out.println(g.selectedRoles.toString());
		}

		if (msg.equalsIgnoreCase("list"))
		{
			String list = g.getPublicPlayerList();
			sendPrivateMessage(user, list);
		}
		if (msg.equalsIgnoreCase("spoilers"))
		{
			Player p = g.getPlayer(user);
			String list = g.getSpoilerPlayerList();
			if (!p.living)
				sendPrivateMessage(user, list);
		}
		if (msg.equalsIgnoreCase("history"))
		{
			sendPrivateMessage(user, g.getHistory());
		}
		if (msg.equalsIgnoreCase("actions"))
		{
			boolean hasRequiredActions = false;
			boolean hasOptionalActions = false;
			String required = "";
			String optional = "";
			if (g.requiredActionsForUser.get(user) != null)
			{
				for (Action a : g.requiredActionsForUser.get(user))
				{
					hasRequiredActions = true;
					if (a.isPublic())
						required = required + "<b>" + a.getCommand() + "</b>: "
								+ a.getDescription() + " (use publically)\n";
					else
						required = required + "<b>" + a.getCommand() + "</b>: "
								+ a.getDescription() + " (use privately)\n";
				}
				if (hasRequiredActions)
					sendPrivateMessage(user,
							"You can use the following actions: \n" + required);
			}
			if (g.optionalActionsForUser.get(user) != null)
			{
				for (Action a : g.optionalActionsForUser.get(user))
				{
					hasOptionalActions = true;
					if (a.isPublic())
						optional = optional + "<b>" + a.getCommand() + "</b>: "
								+ a.getDescription() + " (use publically)\n";
					else
						optional = optional + "<b>" + a.getCommand() + "</b>: "
								+ a.getDescription() + " (use privately)\n";
				}
				if (hasOptionalActions)
					sendPrivateMessage(user,
							"You can use the following actions: \n" + optional);
			}

			if (!hasRequiredActions && !hasOptionalActions)
			{
				sendPrivateMessage(user,
						"It seems that you don't currently have any actions to take.");
				if (g.currentStage == Stage.NIGHT)
					sendPrivateMessage(user,
							"Please hold tight until night is over, then you may talk!");
				if (g.currentStage == Stage.DAY)
					sendPrivateMessage(
							user,
							"Either you don't can't vote for execution this day, you are dead, or this is a bug.");
			}
		}
		g.executePossibleActionsForUser(user, message, false);

	}

}
